<html lang="en">
<!-- Mirrored from bos.asmhackers.net/docs/pmode/docs/protmode.html by HTTrack Website Copier/3.x [XR&CO'2013], Tue, 07 Oct 2014 11:24:06 GMT -->
<head>
<title>"Working in the Protected Mode Environment"</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name=description content=""Working in the Protected Mode Environment"">
<meta name=generator content="makeinfo 4.0">
</head><BODY>

<h1>Table of Contents</h1>
<ul>
<li><a href="#Top">Contents</a>
<li><a href="#Introduction">1 Introduction to Protected Mode</a>
<ul>
<li><a href="#Quick%20look">1.1 A Brief Introduction to Protected Mode</a>
<li><a href="#Advantages">1.2 The Benefits of Using Protected Mode</a>
</ul>
<li><a href="#RM%20Addressing">2 Addressing in Real Mode</a>
<li><a href="#80386%20Registers">3 Registers in the 80386</a>
<li><a href="#RM%20Vector%20Table">4 The Real Mode Vector Table</a>
<li><a href="#Hardware%20Interrupts">5 Hardware Interrupts</a>
<li><a href="#Keyboard">6 Keyboard and the A20 Line</a>
<li><a href="#Selectors%20and%20Descriptors">7 Segment Selectors and Descriptors</a>
<ul>
<li><a href="#Segment%20Selectors">7.1 Segment Selectors</a>
<li><a href="#Tables">7.2 Tables Required in Protected Mode</a>
<li><a href="#Descriptors">7.3 Descriptors</a>
</ul>
<li><a href="#Protected%20Mode%20Privileges">8 Protected Mode Privileges</a>
<ul>
<li><a href="#Protected%20Mode%20Privileges">8.1 Data Access</a>
</ul>
<li><a href="#Multitasking">9 How Multitasking Works</a>
<li><a href="#Exceptions">10 Exceptions on the 80386 Processor</a>
<li><a href="#MMU">11 Memory Management Unit (MMU)</a>
<li><a href="#V86%20Mode">12 Virtual 8086 (V86/VM86) Mode</a>
<li><a href="#Interrupt%20Handling">13 Interrupt Handling in Protected Mode</a>
<li><a href="#Working%20in%20Protected%20Mode">14 Working in Protected Mode</a>
<li><a href="#Protected%20Mode%20Tutorial">15 Protected Mode Tutorial</a>
<li><a href="#About">16 About This Document</a>
<li><a href="#Index">17 Index</a>
</ul>

<p><hr>
Node:<a name="Top">Top</a>,
Next:<a rel=next href="#Introduction">Introduction</a>,
Up:<a rel=up href="#(dir)">(dir)</a>
<br>

<h1>Contents</h1>

<p>This documentation was written due to the increase in the number of
people in the DJGPP mailing list asking for details regarding what
protected mode really is. The documentation contains detailed
information about protected mode. Starters who wish to merely touch
upon "protected mode programming" should generally read only the
introduction, while others who require more information can get into the
depths.

<p>If you have other questions, you can post to the
<a href="mailto:pmode@yahoogroups.com">PMode list</a>. The instructions to join
this list are given at the end of this document.

<ul>
<li><a href="#Introduction">Introduction</a>:                 Introduction to Protected Mode
<li><a href="#RM%20Addressing">RM Addressing</a>:                Real Mode Addressing
<li><a href="#80386%20Registers">80386 Registers</a>:              The 80386 Registers
<li><a href="#RM%20Vector%20Table">RM Vector Table</a>:              The Real Mode Interrupt Vector Table
<li><a href="#Hardware%20Interrupts">Hardware Interrupts</a>:          Hardware Interrupts
<li><a href="#Keyboard">Keyboard</a>:                     The Keyboard and the A20 Line
<li><a href="#Selectors%20and%20Descriptors">Selectors and Descriptors</a>:    Segment Selectors and Descriptors
<li><a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>:    Protected Mode Privileges
<li><a href="#Multitasking">Multitasking</a>:                 How Multitasking Works
<li><a href="#Exceptions">Exceptions</a>:                   Exceptions on the 80386 Processor
<li><a href="#MMU">MMU</a>:                          Memory Management Unit
<li><a href="#V86%20Mode">V86 Mode</a>:                     Virtual 8086 Mode
<li><a href="#Interrupt%20Handling">Interrupt Handling</a>:           Interrupt Handling in Protected Mode
<li><a href="#Working%20in%20Protected%20Mode">Working in Protected Mode</a>:    Working in Protected Mode
<li><a href="#Protected%20Mode%20Tutorial">Protected Mode Tutorial</a>:      Protected Mode Tutorial
<li><a href="#About">About</a>:                        List of Various Contributors
<li><a href="#Index">Index</a>:                        General Index
</ul>

<p><hr>
Node:<a name="Introduction">Introduction</a>,
Next:<a rel=next href="#RM%20Addressing">RM Addressing</a>,
Previous:<a rel=previous href="#Top">Top</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>1 Introduction to Protected Mode</h1>

<ul>
<li><a href="#Quick%20look">Quick look</a>:                   A Brief Look at Protected Mode
<li><a href="#Advantages">Advantages</a>:                   The Benefits of Using Protected Mode
</ul>

<p><hr>
Node:<a name="Quick%20look">Quick look</a>,
Next:<a rel=next href="#Advantages">Advantages</a>,
Up:<a rel=up href="#Introduction">Introduction</a>
<br>

<h2>1.1 A Brief Introduction to Protected Mode</h2>

<p><strong>What is <em>Protected Mode</em>?</strong>

<p>The 80386+ provides many new features to overcome the deficiencies of
8086 which has almost no support for memory protection, virtual memory,
multitasking, or memory above 640K, and also remains compatible with the
8086 family. In <a href="http://www.midpec.com/djgpp/">DJGPP</a>, the 386,
486, etc. are considered to be identical. The points made about the 386
apply to all its successors as well.

<p>The 8086 runs in only one mode - the real mode. When Intel engineers
designed the 286, they wanted to support extra features that would be
incompatible with the 8086. They also wanted to maintain 8086
compatibility. To satisfy these requirements, the 286 uses two
modes - <em>Real Mode</em> and <em>Protected Mode</em>. Real mode, the
default, makes the chip act like an 8086 with only minor
enhancements. There is a huge difference when it comes to protected
mode. Almost all programs designed to run on an 8086 won't run under
protected mode without major changes. <em>DOS is one of these
programs</em>.

<p>The 386 has all the features of the 8086 and 286, with many more
enhancements. The default, as in the earlier processors, is real
mode. Like the 286, the 386 can operate in protected mode. However, the
protected mode on 386 is vastly different internally. Protected mode on
the 386 offers the programmer better protection and more memory than on
the 286. The 386 also supports a third mode, <dfn>Virtual 8086 (V86)
mode</dfn>. In V86 mode, the 386 operates in protected mode but allows some
programs it is running to use a simulated real-mode environment. That
means programs like DOS can run in protected mode without the need for
switching between real and protected modes. The V86 mode has several
advantages over real mode which are mentioned in the chapters that
follow.

<p><hr>
Node:<a name="Advantages">Advantages</a>,
Previous:<a rel=previous href="#Quick%20look">Quick look</a>,
Up:<a rel=up href="#Introduction">Introduction</a>
<br>

<h2>1.2 The Benefits of Using Protected Mode</h2>

<p>All the 386's special features become available in the processor's
protected mode. Some of the extra powers of this mode are mentioned
here<small>...</small>

<p><strong>Access to 4 gigabytes of memory</strong> - This is the most obvious
difference between protected mode and real mode. Protected mode programs
can use up to 4 GB of memory for data, code and stack space. Using some
undocumented features of the 8086 processors, it is possible for
real-mode programs to access memory above the 1MB limit for data
storage. However, using these techniques for code and stack space is
generally impractical. Of course, you probably won't have 4GB of memory
installed on your system. That brings us to the next feature.

<p><strong>Virtual memory</strong> - The Memory Management Unit (MMU) on the 386
allows virtual memory to be implemented, which makes a program think
that it has 4GB of memory when it has less (actually much less). The 386
and special operating system software simulate the extra memory using a
mass storage (like a hard disk drive). Of course, you need about 4GB of
free disk storage space, but that's another problem.

<p><strong>Address translation</strong> - The MMU also allows addresses to be
translated, or mapped, before use. For example, you might want to
translate all references to a 4KB block at a segment B800H (the CGA text
buffer) to a data buffer in your program. Later, your program could copy
the buffer to the screen. This is useful when redirecting the output of
a program that directly writes to the screen. Translation can also
simulate expanded memory without an expanded memory board. But there are
also certain functions in the later versions of EMS which can't be
emulated by the MMU. But you will hardly require those functions even if
your program is advanced.

<p>Programs work with logical addresses. The 386 converts these logical
addresses into 32-bit linear (non-segmented addresses). The MMU then
converts linear addresses to physical addresses. If the MMU isn't
active, linear and physical addresses are equivalent. Applying this
terminology to real mode, the address B800:0010 is a logical
address. Its equivalent linear address is B8010H. Since real mode
doesn't use the MMU, the physical address is the same as the linear
address.

<p><strong>Improved segmentation</strong> - In real mode, all segments are 64KB
long and are in fixed locations. In protected mode, segments can be as
short as one byte or as long as 4GB. The function
<strong>__djgpp_nearptr_enable()</strong> uses this feature. Attempting to
access memory past the end of a segment will cause an error. If the
segment is 4GB long, then the addresses get wrapped if a program tries
to access beyond the 4GB limit. Segments may start off at any
location. In addition, the programmer determines each segment's intended
use, which the 386 enforces. That is, if the program attempts to write
data into a segment meant for code, the 386 will force an error. You
also can define a segment that covers the entire address range of 4GB
and effectively dispense with segments altogether. All memory references
are then via 32-bit non-segmented pointers. These flat pointers
correspond directly to linear addresses.

<p><strong>Memory protection</strong> - The 386 allows memory to be protected. For
example, a user's program may not be able to overwrite operating system
data. This, combined with the checks on segments, protects programs
against bugs that would crash the computer.

<p><strong>Process protection</strong> - In a similar fashion to memory protection,
different programs (or parts of a program) can be protected from each
other. One program might not have access to another program's data,
while the operating system might have access to everyone's
data. Conversely, user programs may have only limited access to the
operating system's data. This is actually implemented using the page
protection mechanism provided by the MMU.

<p><strong>32-bit registers</strong> - All general-purpose registers on the 386 are
32-bits wide. Except for the E prefix (ex: EAX instead of AX), these
registers have the same names as in the 8086. Two new segment registers
(FS and GS) are also available; they are accessible from all modes but
are most useful in protected mode programs. Real-mode programs can also
access these 32-bit registeres, but they won't use them for indexing
purposes. And using 32-bit registers in protected mode (32-bit protected
mode) will cut down the size of the code generally.

<p><strong>Improved addressing modes</strong> - In real mode, programs can only
form addresses with constant values, the BX or BP register, and the SI
or DI register. In protected mode programs, any register can form
addresses. An index can include a scale factor of two, four or
eight. This allows you to write instructions like <code>MOV EBX,
[EDI][EAX*8]+2</code>.

<p><strong>Multitasking support</strong> - The 386 has special provisions to save
the current processor state and switch to a new task (known as
<dfn>context switch</dfn>). A single instruction can switch contexts
rapidly. This has important ramifications for operating systems and
real-time processing. The 386 also supports nested tasks. A task can
return to its original task using a <dfn>back-link</dfn>.

<p><strong>Hardware debugging</strong> - The 386 has special hardware for
implementing single-step code and data breakpoints. This hardware is
available in real mode with some special techniques.

<p><hr>
Node:<a name="RM%20Addressing">RM Addressing</a>,
Next:<a rel=next href="#80386%20Registers">80386 Registers</a>,
Previous:<a rel=previous href="#Introduction">Introduction</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>2 Addressing in Real Mode</h1>

<p>In the 8086-type processors, memory is organized into bytes (8 bits=1
byte). When dealing with quantities larger than eight bits, the 8086
stores the least significant byte in the lowest address. While that
sounds logical, it's confusing when you're reading listings or memory
dumps because the numbers seem backwards. For instance, the computer
stores the word B800H as two bytes: 00H followed by B8H.

<p>The Intel family of processors use a memory-addressing technique known
as <dfn>segmentation</dfn>. A segment is a region of memory. The computer
can handle multiple segments. In real mode (the one in which DOS
normally runs), each segment is 64K long and there are 65536 possible
segments. But these segments overlap so that each starts 16 bytes after
the one before it. This is why DOS cannot address more than 1MB directly
(65536 * 16 = 1048576 = 1MB). The 8086 and 8088 can only address 1MB
anyway. The 286, 386+ can accomodate much more memory, but DOS cannot
access it directly.

<p>Segments are numbered from 0000H to FFFFH. Since each segment is 64KB
long, we use a value called an <dfn>offset</dfn>, to specify the byte we
want to address. A complete 8086 address always contains a segment and
an offset.

<pre>If a segment is 0040H and the offset is 0102H, we write
0040:0102. Because segments overlap every 16 (10H) bytes, address
0000:0010 is identical to address 0001:0000. Likewise 0040:0000 is the
same as address 0000:0400, which is the same as 0020:0200. The computer
also stores segmented addresses ``backwards''. For instance, 0040:1234
appears like this in the computer's memory (in hex):

34 12 40 00

To verify that all the addresses above are the same, convert them to
linear addresses. To convert a segmented address to linear address,
multiply the segment value by 16 (10H) and add the offset.

So, we have (all in hex)

0040 * 10 + 0000 = 00400
0000 *  0 + 0400 = 00400
0020 * 10 + 0200 = 00400

all of which ultimately point to the same area of memory.
</pre>

<p><hr>
Node:<a name="80386%20Registers">80386 Registers</a>,
Next:<a rel=next href="#RM%20Vector%20Table">RM Vector Table</a>,
Previous:<a rel=previous href="#RM%20Addressing">RM Addressing</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>3 Registers in the 80386</h1>

<p>The 80386 has four general-purpose registers, a flags register, six
segment registers, two index registers, a stack segment register and
pointer, base register and an instruction pointer register. In addition
to these, there are other special registers on the 386, namely:

<pre><strong>GDTR</strong> (Global Descriptor Table Register)
<strong>IDTR</strong> (Interrupt Descriptor Table Register)
<strong>LDTR</strong> (Local Descriptor Table Register)
<strong>TR</strong> (Task Register)
<strong>CR0-CR3</strong> (Control Registers)
<strong>DR0-DR7</strong> (Debug Registers)
</pre>

<p>The figure below shows most of these registers and their
significance. As you can see, the 386+ have a variety of special
registers. They usually aren't useful under DOS, but we'll see some of
them when we look at protected mode extensions to DOS.

<pre><img src="fig2.html" alt="fig2.jpg">
</pre>

<p><hr>
Node:<a name="RM%20Vector%20Table">RM Vector Table</a>,
Next:<a rel=next href="#Hardware%20Interrupts">Hardware Interrupts</a>,
Previous:<a rel=previous href="#80386%20Registers">80386 Registers</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>4 The Real Mode Vector Table</h1>

<p>The 8086 family of processors can respond to 256 different
interrupts. Starting at location 0000:0000 is a table of addresses for
each <dfn>interrupt</dfn>. Each entry in this interrupt vector table is four
bytes long, enough for a segment and an offset. So, we have 1024 bytes
or 1K reserved for the Real Mode Interrupt vector table. If the
processor receives an interrupt 2 (INT 2), for example, it saves the
flags and current values of CS and IP on the stack. It then obtains the
address stored at location 0000:0008 and executes the interrupt service
routine (<dfn>ISR</dfn>) at that address. An <code>IRET</code> instruction in the
ISR signals the end of the interrupt<a rel=footnote href="#fn-1"><sup>1</sup></a> and causes the
processor to resume what it was doing before the interrupt.

<p><hr>
Node:<a name="Hardware%20Interrupts">Hardware Interrupts</a>,
Next:<a rel=next href="#Keyboard">Keyboard</a>,
Previous:<a rel=previous href="#RM%20Vector%20Table">RM Vector Table</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>5 Hardware Interrupts</h1>

<p>A hardware interrupt is a special signal from an I/O device to the
computer. This signal informs the computer that the I/O device requires
attention. The processor will normally stop whatever it is doing to
service the interrupt. When the interrupt completes, the processor
resumes execution where it left off.

<p>Hardware interrupts can come from various sources. For example,
every time you press or release a key, you generate an interrupt. Other
interrupts originate from the clock, printer, serial port, disk drives
and so on. The processor itself causes some interrupts. <code>INT 0</code> for
instance, occurs when a program attempts to divide by zero. These are
all hardware interrupts. Hardware interrupt handling is perhaps one of
the most important functions in protected mode. Badly written hardware
interrupt handlers can cause disasters.

<p>The 8259 Programmable Interrupt Controller (<dfn>PIC</dfn>) on the
motherboard manages all hardware interruptrs. These controllers take
interrupt signals from various devices and convert them to specific
interrupts for the processor.

<p>Tha table below shows the hardware interrupts in real mode with their
corresponding PIC interrupt request inputs (known as <dfn>IRQ</dfn>
lines). Do not confuse IRQ numbers with interrupt numbers. For example,
the keyboard connects to IRQ1, which sends INT 9 to the CPU. The PICs
can be reprogrammed to generate different interrupt numbers for each
IRQ. This technique is generally used by screen trapping programs and
also by DOS Extenders such as go32.

<p>The PICs also control the priority of interrupts. For example, the clock
(on IRQ 0) has a higher priority than the keyboard (IRQ 1). If the
processor is servicing a clock interrupt, the PIC won't generate an
interrupt for the keyboard until the clock's ISR resets the PIC. On the
other hand, the clock can interrupt the keyboard's ISR. The PICs can be
programmed to use a variety of priority schemes, but this is rarely, if
ever, seen in PC programming.

<p>The AT's extra PIC connects to the IRQ 2 of the first PIC. Therefore,
the extra PIC's IRQs (8 through 15) have the same priority as IRQ
2. Disabling IRQ 2 disabled all of the second PICs interrupts.

<p><table><tr align="left"><td>Interrupt <td>IRQ Number <td>Description
<br></tr><tr align="left"><td>00H       <td>-          <td>Divide by zero or divide overflow
<br></tr><tr align="left"><td>02H       <td>-          <td>NMI (Non-maskable Interrupt)
<br></tr><tr align="left"><td>04H       <td>-          <td>Overflow (generated by INTO)
<br></tr><tr align="left"><td>08H       <td>0          <td>System timer
<br></tr><tr align="left"><td>09H       <td>1          <td>Keyboard
<br></tr><tr align="left"><td>0AH       <td>2          <td>Interrupt from second PIC
<br></tr><tr align="left"><td>0BH       <td>3          <td>COM2
<br></tr><tr align="left"><td>0CH       <td>4          <td>COM1
<br></tr><tr align="left"><td>0DH       <td>5          <td>LPT2
<br></tr><tr align="left"><td>0EH       <td>6          <td>Floppy Disk
<br></tr><tr align="left"><td>0FH       <td>7          <td>LPT1
<br></tr><tr align="left"><td>70H       <td>8          <td>Real Time Clock
<br></tr><tr align="left"><td>71H       <td>9          <td>General I/O
<br></tr><tr align="left"><td>72H       <td>10         <td>General I/O
<br></tr><tr align="left"><td>73H       <td>11         <td>General I/O
<br></tr><tr align="left"><td>74H       <td>12         <td>General I/O
<br></tr><tr align="left"><td>75H       <td>13         <td>Coprocessor
<br></tr><tr align="left"><td>76H       <td>14         <td>Hard Disk
<br></tr><tr align="left"><td>77H       <td>15         <td>General I/O
<br></tr></table>

<p>You can stop interrupts from disturbing an important section of code in
several ways. The <code>CLI</code> instruction disables all interrupts except
the nonmaskable interrupt <dfn>NMI</dfn> since the NMI, which does not go
through a PIC cannot be disabled this way<a rel=footnote href="#fn-2"><sup>2</sup></a>. In addition, PICs
can be reprogrammed to turn off specific interrupts.

<p><hr>
Node:<a name="Keyboard">Keyboard</a>,
Next:<a rel=next href="#Selectors%20and%20Descriptors">Selectors and Descriptors</a>,
Previous:<a rel=previous href="#Hardware%20Interrupts">Hardware Interrupts</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>6 Keyboard and the A20 Line</h1>

<p>Normally, we would expect the 80386 to wrap addresses in real
mode. Anticipating this, the AT motherboard designers routed the
<code>A20</code> line through the keyboard controller. Ordinarily, the
controller blocks A20 from reaching the memory chips. A special command
to the keyboard controller can enable the A20, and another command can
disable it again later. This so-called A20 gate is essential to
accessing extended memory, whether in real or protected
mode<a rel=footnote href="#fn-3"><sup>3</sup></a>.

<p><hr>
Node:<a name="Selectors%20and%20Descriptors">Selectors and Descriptors</a>,
Next:<a rel=next href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>,
Previous:<a rel=previous href="#Keyboard">Keyboard</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>7 Segment Selectors and Descriptors</h1>

<ul>
<li><a href="#Segment%20Selectors">Segment Selectors</a>:            Segment Selectors
<li><a href="#Tables">Tables</a>:                       Tables Required in Protected Mode
<li><a href="#Descriptors">Descriptors</a>:                  Descriptors
</ul>

<p><hr>
Node:<a name="Segment%20Selectors">Segment Selectors</a>,
Next:<a rel=next href="#Tables">Tables</a>,
Up:<a rel=up href="#Selectors%20and%20Descriptors">Selectors and Descriptors</a>
<br>

<h2>7.1 Segment Selectors</h2>

<p>Understanding segments is the key to understanding protected
mode. Protected mode segments have little in common with real-mode
segments. A protected-mode segment register holds a 16-bit segment
selector (see the figure below). Unlike in real mode, the selector has
nothing to do with the segment's location in memory. Instead, the value
in the register is an index into a table of segment descriptors. Each
descriptor defines one segment and determines where the segment resides,
the segment type, and other important parameters such as the access
rights.

<pre><img src="fig3.html" alt="fig3.jpg">
</pre>

<p>The selector contains three fields. The lowest two bits (RPL) pertain to
the 386's protection mechanism which is explained shortly. The next bit,
TI, determines which table of descriptors defines the segment.

<p>There are three segment descriptor tables:

<ol type=1 start=1>
</p><li>The Global Descriptor Table (GDT)
<li>The Interrupt Descriptor Table (IDT)
<li>The Local Descriptor Table (LDT)
</ol>

<p>Segment selectors never refer to the IDT. If TI is zero, the segment's
definition is in the GDT. If it is one, the LDT contains the definition.

<p><hr>
Node:<a name="Tables">Tables</a>,
Next:<a rel=next href="#Descriptors">Descriptors</a>,
Previous:<a rel=previous href="#Segment%20Selectors">Segment Selectors</a>,
Up:<a rel=up href="#Selectors%20and%20Descriptors">Selectors and Descriptors</a>
<br>

<h2>7.2 Tables Required in Protected Mode</h2>

<p>Each descriptor table can hold upto 8192 descriptors. The <code>INDEX</code>
bits (bits 15 through bit 3) in the selector determine which descriptor
to use.

<p>The GDTR and IDTR registers determine the location of the GDT and IDT
respectively. Each contains a 32-bit address and a 16-bit limit. The
limit is one less than the length of the table in bytes. The GDTR and
IDTR are 48-bit registers. The address is linear rather than a
segment-offset pair. Each table can contain upto 64KB or 8192
descriptors.

<p>The GDT, as its name implies, is global; even when the system is
multitasking, all tasks share the GDT. This is also true of the IDT -
each task uses the same one. If one task changes the GDT or IDT, all
tasks are affected.

<p>The LDTR determines the location of the LDT. Unlike the GDT, each task
usually has its own LDT. Unlike the GDTR, the LDTR does not contain a
48-bit address and limit. Instead, it holds a segment selector that must
point to a special entry in the GDT. This GDT entry points to the
LDT. The GDT may contain pointer to several LDTs.

<p>The IDT is analogous to the real-mode interrupt vector table. Each
descriptor defines the response to one of the 256 possible
interrupts. Even though the IDT can contain upto 8192 descriptors, any
more than 256 is a waste.

<p>The figure below show the logical format of a basic descriptor table
entry. Also, other special types of descriptors are also shown.

<pre><img src="fig4.html" alt="fig4.jpg">
<img src="fig5.html" alt="fig5.jpg">

<img src="fig6.html" alt="fig6.jpg">
</pre>

<p><hr>
Node:<a name="Descriptors">Descriptors</a>,
Previous:<a rel=previous href="#Tables">Tables</a>,
Up:<a rel=up href="#Selectors%20and%20Descriptors">Selectors and Descriptors</a>
<br>

<h2>7.3 Descriptors</h2>

<p>Two fields in the segment descriptor are particularly interesting. The P
bit (bit 47) determines whether the segment is present. An operating
system can clear this bit to create a virtual segment. When a program
tries to use a virtual segment, the 386 generates an error. The
operating system can then load the segment from the disk and try
again. When P is clear, bits 0 through 39 and 48 through 63 can contain
any values. The operating system could store a disk address here, for
example. But this is unsuitable is the segment size is
large. Fortunately, the 386 provides a better way to use virtual
memory.

<p>The other interesting field is the A bit (bit 40). The 386 sets this bit
when any program <em>writes</em> to the segment. Our crude virtual memory
system might use this bit to decide whether it should write a segment to
disk before making it absent and reusing its space.

<p>Another question is how a descriptor can specify a segment from one byte
to 4GB long. The limit field given is only 20 bits. This is where the G
bit (bit 55) comes into play. If G is zero, the limit field corresponds
to one segment's maximum legal offset (one less than its length). If G
is one, however, the 386 shifts the limit field 12 places left to make a
32-bit limit. The 386 fills the bottom 12-bits with ones.

<pre><em>For example</em>

If a dscriptor has a limit field of one and G is one, the actual limit
is 1FFFH. When G is one and limit is zero, the limit is FFFFH.
</pre>

<p>This scheme allows us to specify a segment with a length of less than
1 Mbyte or a multiple of 4 Kbytes. When G is zero, the segment can range
from one byte to 1 Mbyte long. When G is one, the segment can range from
4 Kbytes to 4 Gbytes in length (in 4 Kbytes steps).

<p>It is possible to create two or more descriptors that point to the same
area of memory. An operating system, for example, might load a file into
a data segment and jump to a code segment that starts in the same
place. This process is known as <dfn>aliasing</dfn>. The operating system
must have some way of loading the GDT and other tables. Therefore, it
will usually have a data segment alias to the GDT. Some systems set up a
data segment that covers all 4GB of memory. Tables can then be written
directly with that data sgement. Operating systems rarely allow user
programs to access the GDT, IDT and other system tables directly.

<p>The processor reserves the first slot of the GDT. The selector for this
slot is the <dfn>null selector</dfn>, and using it always causes an
error. The null selector's descriptors should be all zeros. Non-zero
values work but you never know ;-).

<p><hr>
Node:<a name="Protected%20Mode%20Privileges">Protected Mode Privileges</a>,
Next:<a rel=next href="#Multitasking">Multitasking</a>,
Previous:<a rel=previous href="#Selectors%20and%20Descriptors">Selectors and Descriptors</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>8 Protected Mode Privileges</h1>

<p>Protected mode gets its name from the 386's privilege protection. Each
program has a privilege level, or <dfn>PL</dfn>, from zero to three. Programs
at PL0 can execute any instruction and access any data. Programs at PL3
can't execute certain instructions; they also can't access data that
belong to more privileged programs. Each segment descriptor has a
<dfn>Descriptor Privilege Level (DPL)</dfn> that the 386 uses for
protection. The 386 also controls which programs can execute I/O
instructions.

<p>A privilege hierarchy is important for supporting modern operating
systems. In a typical operating system, the main kernel runs at
PL0. Other parts of the operating system might run at PL1. Device
drivers can run at PL2; they need to do direct device I/O. User programs
in this system would run at PL3. This scheme has many advantages. In
particular, a malicious program can't damage the operating system or
other user programs.

<pre>
PL0 programs alone can execute the following instructions:

&#149;HLT
&#149;CLTS
&#149;LGDT
&#149;LIDT
&#149;LLDT
&#149;LTR
&#149;LMSW
&#149;MOV (to/from control/debug/test registers)

On 486 systems

&#149;INVD
&#149;WBINVD
&#149;INVLPG

On Pentium and above

&#149;RDMSR
&#149;WRMSR
&#149;RDTSC

</pre>

<p>The <dfn>IOPL</dfn> field in the EFLAGS register allows the operating system
to control who can do I/O. These two bits determine the minimum
privilege level a program must have to execute I/O instructions (CLI,
STI, IN, INS, OUT and OUTS). If IOPL is zero, only PL0 programs can do
I/O. If IOPL is 3, all programs can execute I/O instructions. Only a PL0
program can modify the IOPL flags. When other programs modify the flags,
IOPL doesn't change! Leaving IOPL=3 makes life easy for DOS Extenders,
but it can cause major problems since real-mode programs mostly use
direct I/O.

<p>A program's privilege level is equal to the RPL field of the selector in
the CS register. This is the current privilege level or <dfn>CPL</dfn>. You
can't directly modify the CS register so that it has a different
RPL. The same holds true for SS as well.

<h2>8.1 Data Access</h2>

<p>Programs can't load a sgement register with just any selector. When a
data segment register (DS, ES, FS or GS) is loaded, the 386 checks the
DPL against the program's CPL and the selector's RPL. The 386 first
compares the CPL to the RPL. The largest one becomes the <dfn>effective
privilege level (EPL)</dfn>. If the DPL is greater than ot equal to the EPL,
the 386 loads the sgment register; otherwise an error occurs.

<p>The SS register must be loaded with a segment whose DPL and CPL are
equal. The 386 also checks to make sure a stack segment is readable,
writeable and present.

<p>The 386 provides a special stack segment type. You can also use a plain
data segment for a stack, if you wish. A stack segment's limit field
indicates the lowest legal offset in the segment.

<p>It is always valid to load a null selector (0 through 3) into a segment
register. However, any attempt to access memory via the selector will
cause an error as expected.

<p><hr>
Node:<a name="Multitasking">Multitasking</a>,
Next:<a rel=next href="#Exceptions">Exceptions</a>,
Previous:<a rel=previous href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>9 How Multitasking Works</h1>

<p>The 386, as mentioned earlier, has support for <dfn>multitasking</dfn>,
i.e. running several processes concurrently. In reality, however, they
do not run concurrently. It only appears to the user as though they were
all running at the same time.

<p>The 386 uses the Task State Segments (TSSs) to support multitasking. The
TSS descriptor points to a buffer which must be at least 104 bytes
long. In addition to multitasking, TSSs can also be used for hardware
interrupt handling (using task gates in the IDT). The TSS selector is
neither readable nor writeable. Generally, a TSS alias is created, which
is nothing but a "data type" segment pointing to the TSS buffer. TSS
selectors <em>always</em> appear in the GDT, never in LDT or IDT. However,
as mentioned above, task gates may appear in the IDT. The processor uses
the TSS selector internally.

<p>Since a multitasking switch requires the processor state to be saved,
the buffer mostly contains the contents of the hardware registers. When
a task switch occurs, the processor saves various details in the TSS
buffer automatically. This process is very quick and hence not many CPU
cycles are wasted in switching to a new task. Before a task is initially
started, the operating system has to fill in certain entries in the TSS
buffer.

<p>Notice the slots for stack segments and pointers for PL0, PL1 and PL2
near the top of the TSS. A program must maintain separate tasks for each
privilege ring it may use. In particular the PL0 stack segments and
pointers are a must. Otherwise, the processor may shut down due to a
double fault in case of an interrupt.

<p>A task switch may occur during a "far jump" or a "far call". The
offset of the call or jump is simply ignored. The values in the TSS are
loaded into the registers and the new task beings to execute. The
selector referred by the jump or call must be a TSS selector or a task
gate. The task gate contains the TSS selector. But unlike the TSS
selector, the task gate may occur in the GDT, IDT or LDT. The EPL must
always be less than or equal to the TSS's DPL as in case of the normal
segment selectors.

<p>The 386 also supports nested tasks. It handles nested tasks using the NT
bit in the EFLAGS register. Whenever a task "calls" another task, the
386 stores the old task's TSS selector in the "back-link" field of the
new TSS. Also, the NT bit in the EFLAGS register is set. When the new
task wishes to return to the old one, it issues an IRET
instruction<a rel=footnote href="#fn-4"><sup>4</sup></a>.

<p>The TSS aren't reentrant. Whenever a task is running, the 386 sets the
BUSY bit in the TSS selector to indicate this. This is done to prevent
recurive calling of tasks.

<p>As mentioned earlier, the TSS must be at least 104 bytes long. The size
of the TSS may extend to any size. The 386 contains a pointer to an I/O
bitmap in the last field. The size of this bitmap is usually 8K, but may
be lesser. The I/O bitmap is optional. If the size of the I/O bitmap is
lesser, entries past the end of this bitmap are considered as
"1s". Each bit in the I/O bitmap corresponds to one I/O port. If a
task tries to do I/O, the 386 checks the task's CPL against the IOPL. If
the CPL is less than or equal to the IOPL, access is granted, otherwise
the 386 checks the I/O bitmap. If the bit corresponding to the I/O port
used is zero, the 386 allows access, otherwise it denies access. A
bitmap should always end with 0FFh.

<pre><img src="fig7.html" alt="fig7.jpg">
</pre>

<p><hr>
Node:<a name="Exceptions">Exceptions</a>,
Next:<a rel=next href="#MMU">MMU</a>,
Previous:<a rel=previous href="#Multitasking">Multitasking</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>10 Exceptions on the 80386 Processor</h1>

<p>The 386 has support for 256 interrupts (or exceptions) just as in the
8086. The Interrupt Descriptor table (IDT) contains the definition for
each of these interrupts. The IDT can have 8192 entries. But if more
than 256 of these entries are present, they simply remain unused. The
IDT may contain trap gates, interrupt gates or task gates. A trap gate
is one that does not clear interrupts before entering the exception
handler. However, an interrupt gates disables all interrupts before
entering the handler. Details about task gates have been given elsewhere
in this document. See <a href="#Multitasking">Multitasking</a>.

<p>Interrupts may be caused due to external hardware (which comes through
the PIC. See <a href="#Hardware%20Interrupts">Hardware Interrupts</a>.), may be caused by the processor
itself, or may be a software interrupt. Carefully handling processor
generated and hardware interrupts is one of the major tasks of an
operating system. Slightest errors in these interrupt handlers may
result in disasters and blue screens ;-).

<p>The processor generated 386 exceptions can be classified into
<em>faults, traps and aborts</em>.

<p>A fault is a correctable error. Most invalid operations result in
faults. When a fault occurs, the CS:EIP points to the instruction that
caused the fault. Faults are considered to be the least serious
exceptions. The most common of these faults is the <strong>"General
Protection Fault (GPF)"</strong>.

<p>Traps accur whenever a software interrupt occurs. Software interrupts
are caused due to the execution of INT and INTO instructions. When a
trap occurs, the CS:EIP points to the instruction following the actual
instruction that caused the trap.<a rel=footnote href="#fn-5"><sup>5</sup></a> The system cannot restart traps.

<p>Aborts are serious errors that indicate that there may be a severe
problem with the operating system itself. The <strong>Double Fault</strong> and
<strong>FPU Overrun</strong> are considered as aborts.

<p>The table below shows the various exceptions with their classifications:

<p><table><tr align="left"><td>Exception (#num)                  Type
<br></tr><tr align="left"><td>Divide Error (0)                  Fault
<br></tr><tr align="left"><td>Debug (1)                         F/Trap
<br></tr><tr align="left"><td>Breakpoint (3)                    Trap
<br></tr><tr align="left"><td>Overflow (4)                      Trap
<br></tr><tr align="left"><td>Bounds Check (5)                  Fault
<br></tr><tr align="left"><td>Bad Opcode (6)                    Fault
<br></tr><tr align="left"><td>No Coprocessor (7)                Fault
<br></tr><tr align="left"><td>Double Fault (8)                  Abort
<br></tr><tr align="left"><td>Coprocessor Overrun (9)           Abort
<br></tr><tr align="left"><td>Invalid TSS Segment (0A)          Fault
<br></tr><tr align="left"><td>Segment not Present (0B)          Fault
<br></tr><tr align="left"><td>Stack Fault (0C)                  Fault
<br></tr><tr align="left"><td>General Protection Fault (0D)     Fault
<br></tr><tr align="left"><td>Page Fault (0E)                   Fault
<br></tr><tr align="left"><td>Coprocessor Error (10)            Fault
<br></tr></table>

<p><hr>
Node:<a name="MMU">MMU</a>,
Next:<a rel=next href="#V86%20Mode">V86 Mode</a>,
Previous:<a rel=previous href="#Exceptions">Exceptions</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>11 Memory Management Unit (MMU)</h1>

<p>The 386 has at least two facilities to support memory management. They
are:

<ol type=1 start=1>
</p><li>Segmentation
<li>Paging
</ol>

<p>Among the two types, use of the segmentation mechanism is a must, while
paging is optional to the user. <dfn>Paging</dfn> provides a mechanism to
implement <em>virtual memory</em> used by almost all operating systems
today. <em>CWSDPMI, the official DJGPP DPMI server, uses this
too</em>. The advantage of using the paging mechanism is that you can
restrict access to specific portions of the memory, while that  would be
hard to do with a segmentation scheme. You can enable paging using the
CR0 register. Segments are used to keep track of data, code and the
stack a certain program is using. However, an operating system might
also use a single selector that covers the entire 4GB of addressable
space and described earlier in this document. See <a href="#Advantages">Advantages</a>.

<p>Enabling paging, however isn't as simple as setting bit 31 of CR0. You
need to set up the <em>Page Directory Entries</em> and the <em>Page
Table Entries</em>, the <em>PDEs and PTEs</em>. The PDEs and PTEs are actually
tables which are used to convert the logical address into the physical
address. See <a href="#Advantages">Advantages</a>.

<p>As with most other functionality, only PL0 programs can activate the
MMU. User programs never know that an MMU exists! The pages are
classified as User/System. PL0 programs can access any page. PL3
programs can access a "User" page, but not a system page. Since 4GB of
memory is often not available on most systems, the page tables for these
aren't usually setup. The corresponsding entries in the PDEs are marked
as "not present".

<p>The MMU uses two types of tables to translate addresses - <em>the Page
Directory Entry and the Page table Entries</em>. Each PDE corresponds to 4
Megabytes of contiguous memory. The PDE contains a pointer to the
starting of the coressponding pgae tables. These PTEs can be used to set
permissions for 4K blocks within the PDEs 4M area. The PTEs also contain
the actual physical address. Note that the PDE contains the
<em>Physical Address</em> of the page tables. To translate a linear
address into a physical address, the MMU looks at bits 31-22 of the
linear address. This is used to select the PDE in concern. Bits 21-12
are used to select one of the 1024 PTEs in the page table selected. The
lower 12 bits form the lower 12-bits of the physical address.

<p>Now, the question is how the MMU finds where the Page Directories are
present. The CR3 register holds the base address of the PDEs. Hence, it
is also known as the <em>PDBR (Page Directory Base
Register)</em><a rel=footnote href="#fn-6"><sup>6</sup></a>

<pre><img src="fig8.html" alt="fig8.jpg">
</pre>

<p><hr>
Node:<a name="V86%20Mode">V86 Mode</a>,
Next:<a rel=next href="#Interrupt%20Handling">Interrupt Handling</a>,
Previous:<a rel=previous href="#MMU">MMU</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>12 Virtual 8086 (V86/VM86) Mode</h1>

<p>As mentioned earlier in this document, the 80386 has a third mode called
the V86 mode. In this mode, the 80386 behaves exactly like an 8086 with
a few minor exceptions. In V86 mode, the CPU may not issue any of the
privileged instructions such as LGDT, LIDT, LLDT, SLDT, ARPL, LAR, LSL,
LTR, VERR, VERW, INVD, WBINVD, WRMSR, RDMSR, etc. However, unlike the
real mode, the MMU is active in the V86 mode. Therefore, the operating
system still has control over a V86 task, although it runs just like in
real mode. Since privileged instructions cannot be executed, the OS can
prevent system crashes or malicious programs from destroying any data.

<p>A task is said to be a V86 task when the VM bit in the EFLAGS register
is set. Only a PL0 program can set this bit. The bit can also be set in
the TSS before the task is executed. The advantage of a having a V86
task rather than a real mode task is obvious - it's due to security
reasons. The other reason is that the time taken by the CPU to switch
from protected mode to real mode is considerable and greatly slows down
the program. By running the program in V86 mode, the program is actually
executed faster.

<p>A V86 task, just like a real mode program, uses segments and offsets
rather than a selector:offset pair. It can access 1MB of memory. A V86
task always runs at PL3. They can do I/O only if the IOPL is 3 or if the
TSS bitmap allows them to do so. If IOPL is less than 3, then the CPU
generates a General Protection Fault whenever the V86 task attempts to
execute the following instructions - CLI, STI, INT, IRET, LOCK, PUSHF
and POPF.

<p><hr>
Node:<a name="Interrupt%20Handling">Interrupt Handling</a>,
Next:<a rel=next href="#Working%20in%20Protected%20Mode">Working in Protected Mode</a>,
Previous:<a rel=previous href="#V86%20Mode">V86 Mode</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>13 Interrupt Handling in Protected Mode</h1>

<p>Interrupt Handling is one of the most important tasks of any operating
system. In particular, without handling the hardware interrupts
correctly, anything could happen. The system could crash or cause
unusual problems. This section gives an overview of interrupt handling
in <em>Protected Mode</em> and <em>V86 Mode</em>.

<p>Interrupt handling in Protected Mode has been mentioned previously in
this document. See <a href="#Exceptions">Exceptions</a>.

<p>Interrupt handling in V86 mode is slighly more complex. Although the
processor is in V86 mode, the interrupt handling still occurs in
protected mode. Since the segment registers will most probably contain
garbage values for the selectors, the 386 zeros all segment registers
before calling the appropriate interrupt handler. Keep in mind that
we're talking of hardware interrupts here, not the ones generated by
the INT instruction. The SS will contain the selector for the PL0 stack
in the Task State Segment. The structure of the VM86 stack frame which
is pushed into the PL0 stack is as shown in the figure below.

<pre><img src="fig9.html" alt="fig9.jpg">
</pre>

<p>When the <code>General Protection Fault</code> occurs, it can be either due to
the fact that a V86 task was interrupted or it could be due to an
interrupt in a true protected mode program. To differentiate between the
two, the handler can look at the EFLAGS register to check if a V86 task
was running. If a V86 task generated the interrupt, the interrupt
handler can look at the offending instruction. Once the cause of
interrupt is known, the operating system can choose to emulate the
instruction (instructions like CLI, STI, etc.). or simply terminate the
program or take any other action.

<p><hr>
Node:<a name="Working%20in%20Protected%20Mode">Working in Protected Mode</a>,
Next:<a rel=next href="#Protected%20Mode%20Tutorial">Protected Mode Tutorial</a>,
Previous:<a rel=previous href="#Interrupt%20Handling">Interrupt Handling</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>14 Working in Protected Mode</h1>

<p>Working in Protected Mode requires that you first switch to protected
mode. To switch to protected mode and do some <code>real</code> work, you need
to follow these steps:

<ol type=1 start=1>
</p><li>Setup the Global Descriptor Table (GDT)
<li>Setup the Interrupt Descriptor Table (IDT)
<li>Reprogram the PICs so that they generate different interrupts
<li>Setup the TSS
<li>Setup Page Tables and CR3 (perhaps you may not require this)
<li>Set bit 0 of CR0
<li>Load the Task Register (TR)
<li>Jump to the TSS selector
</ol>

<p>Setting up the GDT and IDT should be easy. Create the descriptors and
then load GDTR with the address and length of the table. The programs by
<a href="mailto:alexfru@chat.ru">Alexei A Frounze</a> describes all this.

<p>Setting up the TSS can be easy, too, if you follow a neat
procedure. Finally, do a <em>far</em> jump to the TSS and that should do
it.

<p><hr>
Node:<a name="Protected%20Mode%20Tutorial">Protected Mode Tutorial</a>,
Next:<a rel=next href="#About">About</a>,
Previous:<a rel=previous href="#Working%20in%20Protected%20Mode">Working in Protected Mode</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>15 Protected Mode Tutorial</h1>

<p>An excellent set of programs have been written by
<a href="mailto:alexfru@chat.ru">Alexei A Founze</a> and can be downloaded from
<a href="http://members.xoom.com/~alexfru/">his website</a> or get that from
<a href="http://www.midpec.com/djgpp/protmode/pmtuts.zip">here</a>.

<p>To run these set of programs, you'll need a system with the following
configuration.

<ul>
<li>80386 or a better CPU
<li>DOS 5.0+ or Windows 9x in <em>MSDOS mode</em> (NOT DOS box)
<li>Absence of drivers such as EMM386 (and preferably HIMEM.SYS)
<li>Around 2MB RAM
<li>VGA card / SVGA card. 
</ul>

<p>The following is a brief description of each of the programs:

<ol type=1 start=1>
</p><li>Switches to PMode and back to real mode using CR0. 
<li>Sets up GDT, goes to PMode, prints "Hello from PMode!" and goes
back. 
<li>The IDT is setup for software ISR (Int 20h) and divide by zero
exception (Int 0). The prorgam shows work of these handlers. 
<li>The same GDT as before, IDT is setup for all exceptions,  you may
now see type and address of an exception. 
<li>The same GDT as before, almost the same IDT as in TUT04. Two IDT
entries and IRQ handlers are added - IRQ0 (timer) and IRQ1
(keyboard). It reprograms the PIC in order to handle IRQs in Protecte
Mode. 
<li>Almost the same as 5. Task switching is added. 
<li>Multitasking example. 
<li>Demo of page translation. 
<li>This tutorial is a bit different from the seventh one. It doesn't
use TSS for task switchings. It uses stack-based switching instead. 
<li>This tutorial shows Big/Unreal Mode - how to access 4GB of memory
without switching to protected mode. 
<li>It's almost the same as 7. The only difference is that the
tasks are 32-bit. 
<li>Same as 11 except that two LDTs are added for each PL3 task. 
<li>Multitasking. First time we run a Virtual 8086 machine here. 
<li>Advanced V86 stuff. A software Int nn is now supported for V86
tasks. 
<li>A working V86 monitor - similar to a DOS box. 
<li>The same V86 monitor. Quite a few changes (Int 1 - single-step
trap is now passed to V86 task).
</ol>

<p><hr>
Node:<a name="About">About</a>,
Next:<a rel=next href="#Index">Index</a>,
Previous:<a rel=previous href="#Protected%20Mode%20Tutorial">Protected Mode Tutorial</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>16 About This Document</h1>

<p>This document is written and maintained by
<a href="http://www.midpec.com/whois/prashant.html">Prashant TR</a>. If you
have comments, questions or any suggestions, please send E-Mail to
<a href="mailto:tr@midpec.com">Prashant TR</a> or to the
<a href="mailto:pmode@yahoogroups.com">PMode list</a>. Make sure you're referring
to the latest version of this document on
<a href="http://www.midpec.com/djgpp/protmode/">http://www.midpec.com/djgpp/protmode/</a>. If you have problems
understanding this, or want to raise a question, consider
posting/joining the <a href="mailto:pmode@yahoogroups.com">PMode list</a>. The
instructions to join this list are on <a href="http://www.midpec.com/">http://www.midpec.com/</a>. Even otherwise, you are free to send any
comments there.

<p>The following people have provided valuable comments and information and
made this document a successful one:

<ol type=1 start=1>
</p><li><a href="mailto:alexfru@chat.ru">Alexei A Frounze</a> - Alexei A Frounze has been
working on OS development since a long time. He is also a teacher of
Physics. 
<li><a href="mailto:eliz@is.elta.co.il">Eli Zaretskii</a> - Eli Zaretskii has been
working on <a href="http://www.midpec.com/djgpp/">DJGPP</a> for several
years. He is also the author and maintainer of the
<a href="http://www.midpec.com/djgpp/faq/">DJGPP FAQ</a> and has ported
several Unix packages to DJGPP. (See the
<a href="http://www.midpec.com/djgpp/contrib.html">list of contributors</a>
for various packages).
</ol>

<p><hr>
Node:<a name="Index">Index</a>,
Previous:<a rel=previous href="#About">About</a>,
Up:<a rel=up href="#Top">Top</a>
<br>

<h1>17 Index</h1>

<ul compact>
<li>286: <a href="#Quick%20look">Quick look</a>
<li>32-bit registers: <a href="#Advantages">Advantages</a>
<li>48-bit registers: <a href="#Tables">Tables</a>
<li>4GB of memory: <a href="#Advantages">Advantages</a>
<li>640K limit: <a href="#Quick%20look">Quick look</a>
<li>80386: <a href="#Quick%20look">Quick look</a>
<li>80386 Registers: <a href="#80386%20Registers">80386 Registers</a>
<li>80386 special registers: <a href="#80386%20Registers">80386 Registers</a>
<li>8259 Programmable Interrupt Controller (PIC): <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Abort: <a href="#Exceptions">Exceptions</a>
<li>Access bit: <a href="#Descriptors">Descriptors</a>
<li>Address wrap: <a href="#Keyboard">Keyboard</a>
<li>Addressing modes: <a href="#Advantages">Advantages</a>
<li>Advantages: <a href="#Advantages">Advantages</a>
<li>Aliasing: <a href="#Descriptors">Descriptors</a>
<li>Benefits: <a href="#Advantages">Advantages</a>
<li>BUSY bit: <a href="#Multitasking">Multitasking</a>
<li>CGA text buffer: <a href="#Advantages">Advantages</a>
<li>CLI instruction: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Context switch: <a href="#Advantages">Advantages</a>
<li>CR0-CR3: <a href="#80386%20Registers">80386 Registers</a>
<li>Current privilege level (CPL): <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Data access in protected mode: <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Descriptor privilege level (DPL): <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Descriptors: <a href="#Descriptors">Descriptors</a>
<li>Disabling NMI: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Disk address: <a href="#Descriptors">Descriptors</a>
<li>DOS: <a href="#Quick%20look">Quick look</a>
<li>DR0-DR7: <a href="#80386%20Registers">80386 Registers</a>
<li>Effective privilege level (EPL): <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>EMS board: <a href="#Advantages">Advantages</a>
<li>Exceptions on 80386: <a href="#Exceptions">Exceptions</a>
<li>Expanded Memory: <a href="#Advantages">Advantages</a>
<li>Extended memory: <a href="#Keyboard">Keyboard</a>
<li>Fault: <a href="#Exceptions">Exceptions</a>
<li>GDT Alias: <a href="#Descriptors">Descriptors</a>
<li>GDTR: <a href="#Tables">Tables</a>
<li>GDTR: Global Descriptor Table: <a href="#80386%20Registers">80386 Registers</a>
<li>General-purpose registers: <a href="#80386%20Registers">80386 Registers</a>
<li>Global Descriptor Table (GDT): <a href="#Tables">Tables</a>, <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Granularity bit: <a href="#Descriptors">Descriptors</a>
<li>Hardware debugging: <a href="#Advantages">Advantages</a>
<li>Hardware Interrupt: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Hardware interrupts: <a href="#Exceptions">Exceptions</a>
<li>Hardware Interrupts: Sources: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>I/O bitmap: <a href="#Multitasking">Multitasking</a>
<li>IDTR: <a href="#Tables">Tables</a>
<li>IDTR: Interrupt Descriptor Table: <a href="#80386%20Registers">80386 Registers</a>
<li>Input/Output privilege level (IOPL): <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Interrupt Descriptor Table (IDT): <a href="#Tables">Tables</a>, <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Interrupt handling: <a href="#Interrupt%20Handling">Interrupt Handling</a>
<li>Interrupt priority: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Interrupt Service Routine (ISR): <a href="#RM%20Vector%20Table">RM Vector Table</a>
<li>Interrupts on 80386: <a href="#Exceptions">Exceptions</a>
<li>Introduction: <a href="#Quick%20look">Quick look</a>
<li>IRET instruction: <a href="#RM%20Vector%20Table">RM Vector Table</a>
<li>IRQ lines: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Keyboard and A20: <a href="#Keyboard">Keyboard</a>
<li>LDTR: <a href="#Tables">Tables</a>
<li>LDTR: Local Descriptor Table: <a href="#80386%20Registers">80386 Registers</a>
<li>Linear Address: <a href="#Advantages">Advantages</a>
<li>List of Contributors: <a href="#About">About</a>
<li>List of exceptions: <a href="#Exceptions">Exceptions</a>
<li>List of hardware interrupts: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Local Descriptor Table (LDT): <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Location of LDT: <a href="#Tables">Tables</a>
<li>Logical Address: <a href="#Advantages">Advantages</a>
<li>Memory Management Unit (MMU): <a href="#Advantages">Advantages</a>
<li>Memory Protection: <a href="#Advantages">Advantages</a>
<li>Multitasking: <a href="#Multitasking">Multitasking</a>, <a href="#Advantages">Advantages</a>
<li>Nested tasks: <a href="#Multitasking">Multitasking</a>
<li>Newbies: <a href="#Top">Top</a>
<li>Non-maskable interrupt (NMI): <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Novices: <a href="#Top">Top</a>
<li>NT bit: <a href="#Multitasking">Multitasking</a>
<li>Null selector: <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>NULL selector: <a href="#Descriptors">Descriptors</a>
<li>Page directory base register: <a href="#MMU">MMU</a>
<li>Page directory entry: <a href="#MMU">MMU</a>
<li>Page table entry: <a href="#MMU">MMU</a>
<li>Paging: <a href="#MMU">MMU</a>
<li>PDEs and PTEs: <a href="#MMU">MMU</a>
<li>Physical Address: <a href="#Advantages">Advantages</a>
<li>PIC II: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Present bit: <a href="#Descriptors">Descriptors</a>
<li>Privilege hierarchy: <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Privilege level (PL): <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Privilege protection: <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Privileged instructions: <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Process Protection: <a href="#Advantages">Advantages</a>
<li>Programming PICs: <a href="#Hardware%20Interrupts">Hardware Interrupts</a>
<li>Protected Mode: <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Protected Mode: Introduction: <a href="#Quick%20look">Quick look</a>
<li>Real Mode: <a href="#Quick%20look">Quick look</a>
<li>Real mode segments: <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Real Mode segments: An example: <a href="#RM%20Addressing">RM Addressing</a>
<li>Real Mode: Interrupt Vector Table: <a href="#RM%20Vector%20Table">RM Vector Table</a>
<li>Real Mode: Memory Organization: <a href="#RM%20Addressing">RM Addressing</a>
<li>Real Mode: Offset: <a href="#RM%20Addressing">RM Addressing</a>
<li>Real Mode: Segment overlap: <a href="#RM%20Addressing">RM Addressing</a>
<li>Real Mode: Segmentation: <a href="#RM%20Addressing">RM Addressing</a>
<li>Real Mode: Segments: <a href="#RM%20Addressing">RM Addressing</a>
<li>Real-mode interrupt vector table: <a href="#Tables">Tables</a>
<li>Requestor privilege level (RPL): <a href="#Protected%20Mode%20Privileges">Protected Mode Privileges</a>
<li>Requestor Privilege Level (RPL): <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Security: <a href="#V86%20Mode">V86 Mode</a>
<li>Segment descriptors: <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Segment registers: <a href="#80386%20Registers">80386 Registers</a>
<li>Segment selectors: <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Segment Selectors: <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Segment type: <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Segmentation: <a href="#MMU">MMU</a>, <a href="#Advantages">Advantages</a>
<li>Software interrupts: <a href="#Exceptions">Exceptions</a>
<li>Switching to protected mode: <a href="#Working%20in%20Protected%20Mode">Working in Protected Mode</a>
<li>System crashes: <a href="#V86%20Mode">V86 Mode</a>
<li>Table Indicator (TI): <a href="#Segment%20Selectors">Segment Selectors</a>
<li>Tables in Protected Mode: <a href="#Tables">Tables</a>
<li>Task gate: <a href="#Multitasking">Multitasking</a>
<li>Task State Segments: <a href="#Multitasking">Multitasking</a>
<li>TR: Task Register: <a href="#80386%20Registers">80386 Registers</a>
<li>Trap: <a href="#Exceptions">Exceptions</a>
<li>TSS: <a href="#Multitasking">Multitasking</a>
<li>TSS alias: <a href="#Multitasking">Multitasking</a>
<li>Undocumented: <a href="#Advantages">Advantages</a>
<li>V86 mode: <a href="#V86%20Mode">V86 Mode</a>
<li>V86 Mode: <a href="#Quick%20look">Quick look</a>
<li>Virtual 8086 Mode: <a href="#Quick%20look">Quick look</a>
<li>Virtual memory: <a href="#Descriptors">Descriptors</a>
<li>Virtual Memory: <a href="#Advantages">Advantages</a>
<li>Virtual segment: <a href="#Descriptors">Descriptors</a>
<li>VM bit: <a href="#V86%20Mode">V86 Mode</a>
<li>VM86 Mode: <a href="#Quick%20look">Quick look</a>
<li>VM86 stack frame: <a href="#Interrupt%20Handling">Interrupt Handling</a>
<li>What is Protected Mode?: <a href="#Quick%20look">Quick look</a>
</ul>


<hr><h4>Footnotes</h4>
<ol type="1">
<li><a name="fn-1"></a>
<p>In reality, this hardly
happens. Most BIOSes and even DOS, sometimes, use instructions like
<code>RETF 2</code>, making this INT-IRET sequence unreliable enough for
simulating interrupts in V86 mode. A work-around is to use a special
VM86 stack-frame which is takes care of all this.</p>

<li><a name="fn-2"></a>
<p>By definition the
8086 can't mask the NMI. On the PC, the motherboard, however, does have
the ciruitary to prevent an NMI from occurring. You will rarely need to
disable the NMI. On the ATs, the motherboard controls it with port
70H. Clearing bit 7 of this port will cut off NMI.</p>

<li><a name="fn-3"></a>
<p>Many programs get access to memory beyond the 1 MB limit
by simply enabling the A20. With the A20 enabled, the addresses won't
wrap around, so they can access around 64K of memory above the 1MB limit
without getting to real mode. But then, this can cause several problems
with memory managers, so it must be carefully done</p>

<li><a name="fn-4"></a>
<p>The IRET instruction in the 386's protected mode
has a much different meaning than what it has in real mode. To return
from an interrupt handler in protected mode, IRETD is used.</p>

<li><a name="fn-5"></a>
<p>Traps have nothing to do with
trap gates. A trap can be handled using an interrupt gate or a trap
gate.</p>

<li><a name="fn-6"></a>
<p>Note that the PDE and all PTEs must lie on the
beginning of a 4K block.</p>

</ol><hr>

<hr>
<center><tt><a href="http://www.midpec.com/copyright.html">Copyright</a>
(C) 2000, 2001 <a href="http://www.midpec.com/whois/prashant.html">Prashant TR</a>.
All rights reserved.</tt></center>
<p align=right>
</p>
</BODY>
<!-- Mirrored from bos.asmhackers.net/docs/pmode/docs/protmode.html by HTTrack Website Copier/3.x [XR&CO'2013], Tue, 07 Oct 2014 11:24:09 GMT -->
</html>



